<template>
  <view class="container">
    <!-- 消息列表 -->
    <scroll-view 
      class="message-list" 
      scroll-y 
      :scroll-top="scrollTop" 
      scroll-with-animation
      :enable-back-to-top="true"
      :scroll-anchoring="true"
    >
      <view v-for="(message, index) in messageList" :key="index" class="message-wrapper">
        <!-- 用户消息（右侧） -->
        <view v-if="message.type === 'user'" class="message-item user-message">
          <view class="message-content user-content">
            <view v-if="message.msgType === 'text'" class="text-message">
              {{ message.content }}
            </view>
            <view v-else-if="message.msgType === 'voice'" class="voice-message" @click="togglePlay(message.voiceIndex)">
              <svg class="voice-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
                <path
                  d="M636.16512 957.44l-70.80448-70.8096c107.59168-92.06272 176.03072-228.58752 176.03072-381.31712 0-145.49504-62.2848-276.1216-161.1776-367.77472L651.19232 66.56c117.01248 109.82912 190.51008 265.47712 190.51008 438.60992 0 180.44416-79.77984 341.90848-205.53728 452.27008z"
                  fill="currentColor"></path>
                <path
                  d="M445.08672 766.35648l-72.93952-72.92928c66.28352-36.64384 111.19104-107.16672 111.19104-188.25728 0-73.61536-37.04832-138.5216-93.47072-177.29024l71.62368-71.61344C535.72096 313.97376 583.68 403.88096 583.68 505.16992c0 108.65664-54.95808 204.44672-138.59328 261.18656zM253.96736 591.18592c-39.5776 0-71.66976-32.08192-71.66976-71.67488 0-39.59808 32.08704-71.67488 71.66976-71.67488 39.60832 0 71.68 32.0768 71.68 71.67488 0 39.59296-32.07168 71.67488-71.68 71.67488z"
                  fill="currentColor"></path>
              </svg>
              <text class="voice-duration">{{ formatTime(message.duration) }}</text>
            </view>
          </view>
        </view>

        <!-- 系统消息（左侧） -->
        <view v-else class="message-item system-message">
          <view class="message-content system-content">
            <view class="text-message" v-html="parseMarkdown(message.content)">
            </view>
          </view>
        </view>
      </view>
    </scroll-view>

    <!-- 输入区域 -->
    <view class="input-area">
    <!-- 录音提示 -->
    <view v-if="isRecording" class="record-overlay">
      <view class="record-modal">
        <view class="record-circle" :class="{ 'cancel': isCancel }">
          <svg class="record-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
            <path d="M636.16512 957.44l-70.80448-70.8096c107.59168-92.06272 176.03072-228.58752 176.03072-381.31712 0-145.49504-62.2848-276.1216-161.1776-367.77472L651.19232 66.56c117.01248 109.82912 190.51008 265.47712 190.51008 438.60992 0 180.44416-79.77984 341.90848-205.53728 452.27008z" fill="currentColor"></path>
            <path d="M445.08672 766.35648l-72.93952-72.92928c66.28352-36.64384 111.19104-107.16672 111.19104-188.25728 0-73.61536-37.04832-138.5216-93.47072-177.29024l71.62368-71.61344C535.72096 313.97376 583.68 403.88096 583.68 505.16992c0 108.65664-54.95808 204.44672-138.59328 261.18656zM253.96736 591.18592c-39.5776 0-71.66976-32.08192-71.66976-71.67488 0-39.59808 32.08704-71.67488 71.66976-71.67488 39.60832 0 71.68 32.0768 71.68 71.67488 0 39.59296-32.07168 71.67488-71.68 71.67488z" fill="currentColor"></path>
          </svg>
        </view>
        <view class="record-time">{{ recordDuration }}s</view>
        <view class="record-tip">
          <text v-if="isCancel" class="cancel-text">松开手指取消发送</text>
          <text v-else class="normal-text">正在录音中...</text>
        </view>
      </view>
    </view>

      <!-- 输入框模式 -->
      <view v-if="!isVoiceMode" class="input-mode">
        <!-- 语音按钮 -->
        <view class="voice-btn" @click="switchToVoiceMode">
          <image src="@/static/voice.png" />
        </view>

        <!-- 输入框 -->
        <input class="message-input" type="text" placeholder="请输入消息..." v-model="inputText"
          @confirm="sendTextMessage" />

        <!-- 发送按钮 -->
        <view class="send-btn" :class="{ 'active': inputText.trim() }" @click="sendTextMessage">
          发送
        </view>
      </view>

      <!-- 录音模式 -->
      <view v-else class="voice-mode">
        <!-- 键盘按钮 -->
        <view class="keyboard-btn" @click="switchToInputMode">
          <image src="@/static/keyboard.png" />
        </view>

        <!-- 录音按钮 -->
        <view class="record-btn" :class="{
          'recording': isRecording,
          'cancel': isCancel
        }" @touchstart="startRecord" @touchend="stopRecord" @touchmove="handleTouchMove" @touchcancel="cancelRecord">
          <text class="btn-text">{{ isRecording ? '松开结束' : '按住说话' }}</text>
        </view>
      </view>

      <!-- 操作提示 -->
      <view v-if="isVoiceMode" class="record-hint">向上滑动可取消发送（最长30秒）</view>
    </view>
  </view>
</template>

<script>
import { post } from '@/utils/requestV2.js'

export default {
  data() {
    return {
      // 输入模式状态
      isVoiceMode: false,       // 是否为语音模式
      inputText: '',            // 输入框文本

      // 消息列表
      messageList: [
        {
          type: 'system',
          msgType: 'text',
          content: '您好！我是爱育华医院智能客服小爱，有什么可以帮助您的吗？',
          timestamp: Date.now()
        }
      ],
      scrollTop: 0,             // 滚动位置

      // 录音状态
      isRecording: false,       // 是否正在录音
      isCancel: false,          // 是否取消录音
      recordDuration: 0,        // 录音时长(秒)
      recordTimer: null,        // 录音计时器
      recorderManager: null,    // 录音管理器
      innerAudioContext: null,  // 音频播放管理器

      // 播放状态
      isPlaying: false,         // 是否正在播放
      playingIndex: -1,         // 当前播放的索引

      // 语音列表
      voiceList: []             // 存储录音文件信息
    };
  },

  watch: {
    // 监听消息列表变化，自动滚动到底部
    messageList: {
      handler() {
        this.$nextTick(() => {
          this.scrollToBottom();
        });
      },
      deep: true
    }
  },

  onLoad() {
    // 检查录音功能是否可用
    if (!uni.getRecorderManager) {
      uni.showModal({
        title: '提示',
        content: '当前环境不支持录音功能',
        showCancel: false
      });
      return;
    }

    // 初始化录音管理器
    this.initRecorderManager();

    // 初始化音频播放管理器
    this.innerAudioContext = uni.createInnerAudioContext();
    this.innerAudioContext.onEnded(() => {
      this.isPlaying = false;
      this.playingIndex = -1;
    });

    this.innerAudioContext.onError((res) => {
      console.error('播放错误:', res);
      this.isPlaying = false;
      this.playingIndex = -1;
      uni.showToast({
        title: '播放失败',
        icon: 'none'
      });
    });
  },

  onUnload() {
    // 页面卸载时停止播放和录音
    this.innerAudioContext.stop();
    this.recorderManager.stop();
    clearInterval(this.recordTimer);
  },

  methods: {
    // 初始化录音管理器
    initRecorderManager() {
      // 如果已存在录音管理器，先销毁
      if (this.recorderManager) {
        try {
          this.recorderManager.stop();
        } catch (e) {
          console.log('停止旧录音管理器:', e);
        }
      }

      // 创建新的录音管理器
      this.recorderManager = uni.getRecorderManager();

      // 监听录音开始事件
      this.recorderManager.onStart(() => {
        console.log('录音开始');
      });

      // 监听录音停止事件
      this.recorderManager.onStop((res) => {
        console.log('录音停止:', res);
        if (!this.isCancel && this.recordDuration >= 1) {
          // 保存录音
          const voiceIndex = this.voiceList.length;
          this.voiceList.push({
            tempFilePath: res.tempFilePath,
            duration: Math.floor(res.duration / 1000) // 转换为秒
          });

          // 添加语音消息到聊天列表
          this.messageList.push({
            type: 'user',
            msgType: 'voice',
            duration: Math.floor(res.duration / 1000),
            voiceIndex: voiceIndex,
            timestamp: Date.now()
          });

          // 滚动到底部
          this.scrollToBottom();
          
          // 延迟再次滚动，确保内容渲染完成
          setTimeout(() => {
            this.scrollToBottom();
          }, 50);

          // 发送语音消息进行识别和AI处理
          this.sendVoiceMessage(res.tempFilePath, Math.floor(res.duration / 1000));

        } else if (this.recordDuration < 1 && !this.isCancel) {
          uni.showToast({
            title: '录音时间太短',
            icon: 'none',
            duration: 1000
          });
        }

        // 重置状态
        this.resetRecordState();
      });

      // 监听录音错误事件
      this.recorderManager.onError((err) => {
        console.error('录音错误:', err);
        let errorMsg = '录音失败';

        if (err.errMsg) {
          if (err.errMsg.includes('NotFoundError')) {
            errorMsg = '未找到录音设备，请检查麦克风是否正常';
          } else if (err.errMsg.includes('NotAllowedError')) {
            errorMsg = '录音权限被拒绝，请在设置中开启录音权限';
          } else if (err.errMsg.includes('NotSupportedError')) {
            errorMsg = '当前设备不支持录音功能';
          } else if (err.errMsg.includes('SecurityError')) {
            errorMsg = '录音权限不足，请检查权限设置';
          }
        }

        uni.showToast({
          title: errorMsg,
          icon: 'none',
          duration: 3000
        });
        this.resetRecordState();
      });
    },

    // 切换到语音模式
    switchToVoiceMode() {
      this.isVoiceMode = true;
    },

    // 切换到输入模式
    switchToInputMode() {
      this.isVoiceMode = false;
    },

    // 发送文本消息
    sendTextMessage() {
      if (!this.inputText.trim()) {
        uni.showToast({
          title: '请输入消息',
          icon: 'none'
        });
        return;
      }

      // 添加用户消息到列表
      this.messageList.push({
        type: 'user',
        msgType: 'text',
        content: this.inputText.trim(),
        timestamp: Date.now()
      });

      // 清空输入框
      const userMessage = this.inputText.trim();
      this.inputText = '';

      // 滚动到底部
      this.scrollToBottom();
      
      // 延迟再次滚动，确保内容渲染完成
      setTimeout(() => {
        this.scrollToBottom();
      }, 50);

      // 发送真实AI请求
      this.requestAI(userMessage);
    },

    //发送语音消息（先请求后台接口把语音转换成文字再调用）requestAI处理
    async sendVoiceMessage(voiceFilePath, duration) {
      console.log('发送语音消息:', voiceFilePath, duration);
      try {
        // 显示转换提示
        uni.showLoading({
          title: '正在识别语音...',
          mask: true
        });

        // 读取音频文件并转换为Base64
        const base64Audio = await this.convertAudioToBase64(voiceFilePath);
        // 构建语音转文字请求参数
        const voicePayload = {
          format: 'mp3',
          file: base64Audio
        };

        // 发送语音转文字请求
        const voiceResponse = await uni.request({
          url: 'http://192.168.32.90:2792/voice-to-text/index',
          method: 'POST',
          data: voicePayload,
          header: {
            'Content-Type': 'application/json'
          }
        });

        uni.hideLoading();

        // 检查语音转换是否成功
        if (voiceResponse.statusCode !== 200 || !voiceResponse.data) {
          throw new Error('语音识别失败');
        }

        // 获取转换后的文字
        // 返回数据格式：
        // code: 200
        // data: "{"Result":"喂喂喂喂喂喂。","AudioDuration":2700,"WordSize":0,"RequestId":"f85873e9-9b22-4604-b434-865ecd3665d4"}"
        // msg: "操作成功"

        let recognizedText = '';

        // 检查响应状态
        if (voiceResponse.data.code === 200) {
          try {
            // 解析data字段中的JSON字符串
            const parsedData = JSON.parse(voiceResponse.data.data);
            recognizedText = parsedData.Result || '';
          } catch (parseError) {
            console.error('解析语音识别结果失败:', parseError);
            throw new Error('解析语音识别结果失败');
          }
        } else {
          throw new Error(voiceResponse.data.msg || '语音识别失败');
        }

        if (!recognizedText.trim()) {
          uni.showToast({
            title: '未识别到语音内容',
            icon: 'none',
            duration: 2000
          });
          return;
        }

        // 在语音消息下方显示识别出的文字（可选）
        console.log('识别出的文字:', recognizedText);

        // 显示识别成功提示
        uni.showToast({
          title: '语音识别成功',
          icon: 'success',
          duration: 1000
        });

        // 调用AI处理识别出的文字
        this.requestAI(recognizedText);

      } catch (error) {
        uni.hideLoading();
        console.error('语音转文字失败:', error);

        let errorMessage = '语音识别失败，请重试';
        
        // 检查是否是文件大小错误
        if (error.message && error.message.includes('音频文件过大')) {
          errorMessage = error.message;
        }

        uni.showToast({
          title: errorMessage,
          icon: 'none',
          duration: 3000
        });
      }
    },

    // 将音频文件转换为Base64
    async convertAudioToBase64(filePath) {
      return new Promise((resolve, reject) => {
        // 使用uni.getFileSystemManager读取文件
        const fileManager = uni.getFileSystemManager();

        fileManager.readFile({
          filePath: filePath,
          encoding: 'base64',
          success: (res) => {
            // 检查Base64文件大小（字符数量）
            const base64Size = res.data.length;
            // Base64编码后的大小约为原文件的4/3倍
            // 3MB = 3 * 1024 * 1024 bytes = 3145728 bytes
            // Base64后约为 3145728 * 4/3 ≈ 4194304 字符
            const maxBase64Size = 4194304; // 约3MB的Base64大小
            
            if (base64Size > maxBase64Size) {
              reject(new Error(`音频文件过大，当前大小：${(base64Size / 1024 / 1024 * 0.75).toFixed(2)}MB，最大支持3MB`));
              return;
            }
            
            console.log(`音频文件Base64大小：${(base64Size / 1024 / 1024 * 0.75).toFixed(2)}MB`);
            resolve(res.data);
          },
          fail: (err) => {
            console.error('读取音频文件失败:', err);
            reject(new Error('读取音频文件失败'));
          }
        });
      });
    },

    // 请求AI回复
    async requestAI(userMessage) {
      try {
        // 添加AI正在思考的临时消息
        const thinkingMessageIndex = this.messageList.length;
        this.messageList.push({
          type: 'system',
          msgType: 'text',
          content: '正在思考中...',
          timestamp: Date.now(),
          isThinking: true
        });

        // 滚动到底部
        this.scrollToBottom();
        
        // 延迟再次滚动，确保内容渲染完成
        setTimeout(() => {
          this.scrollToBottom();
        }, 50);

        // 构建请求参数
        let payload = {
          // "prompt": userMessage
          message: userMessage
        };

        // 发送请求到AI
        let res = await post("", payload, {
          showLoading: false // 不显示loading，因为我们有"正在思考"提示
        });

        // 移除"正在思考"的消息
        this.messageList.splice(thinkingMessageIndex, 1);

        // 获取AI回复内容并过滤think标签
        let aiResponse = res.statusCode === 200 || '抱歉，我暂时无法回答您的问题。';

        aiResponse = res.result.output.text

        // 过滤掉 <think> 标签及其内容
        let aiResponseText = this.filterThinkTags(aiResponse);

        // 添加AI回复到消息列表
        this.messageList.push({
          type: 'system',
          msgType: 'text',
          content: aiResponseText,
          timestamp: Date.now()
        });

        // 滚动到底部
        this.scrollToBottom();
        
        // 延迟再次滚动，确保内容渲染完成
        setTimeout(() => {
          this.scrollToBottom();
        }, 100);

      } catch (error) {
        console.error('AI请求失败:', error);

        // 移除"正在思考"的消息（如果存在）
        const thinkingIndex = this.messageList.findIndex(msg => msg.isThinking);
        if (thinkingIndex !== -1) {
          this.messageList.splice(thinkingIndex, 1);
        }

        // 添加错误提示消息
        this.messageList.push({
          type: 'system',
          msgType: 'text',
          content: '抱歉，服务暂时不可用，请稍后再试。',
          timestamp: Date.now()
        });

        // 滚动到底部
        this.scrollToBottom();
      }
    },

    // 过滤think标签的方法
    filterThinkTags(text) {
      if (!text || typeof text !== 'string') {
        return text;
      }

      // 使用正则表达式移除 <think> 和 </think> 标签及其内容
      // 支持多行匹配和贪婪匹配
      const thinkRegex = /<think[\s\S]*?<\/think>/gi;

      // 移除think标签及其内容
      let filteredText = text.replace(thinkRegex, '');

      // 清理多余的空行和空白字符
      filteredText = filteredText
        .replace(/\n\s*\n\s*\n/g, '\n\n') // 将多个连续空行替换为最多两个
        .trim(); // 移除首尾空白

      return filteredText || '抱歉，我暂时无法回答您的问题。';
    },

    // 添加系统回复
    addSystemReply(userMessage) {
      let reply = '';

      // 简单的关键词回复逻辑
      if (userMessage.includes('你好') || userMessage.includes('您好')) {
        reply = '您好！很高兴为您服务，请问有什么可以帮助您的吗？';
      } else if (userMessage.includes('帮助') || userMessage.includes('咨询')) {
        reply = '我可以为您提供各种帮助和咨询服务，请详细描述您的问题。';
      } else if (userMessage.includes('谢谢') || userMessage.includes('感谢')) {
        reply = '不客气！很高兴能够帮助到您，还有其他问题吗？';
      } else {
        reply = '我收到了您的消息，正在为您处理中，请稍等...';
      }

      this.messageList.push({
        type: 'system',
        msgType: 'text',
        content: reply,
        timestamp: Date.now()
      });

      this.scrollToBottom();
    },

    // 滚动到底部
    scrollToBottom() {
      this.$nextTick(() => {
        // 使用更大的数值确保滚动到最底部
        this.scrollTop = 0;
        this.$nextTick(() => {
          this.scrollTop = 999999;
        });
      });
    },

    // 重置录音状态
    resetRecordState() {
      this.isRecording = false;
      this.isCancel = false;
      this.recordDuration = 0;
      if (this.recordTimer) {
        clearInterval(this.recordTimer);
        this.recordTimer = null;
      }
    },

    // 开始录音
    startRecord(e) {
      // 先检查是否支持录音功能
      if (!uni.getRecorderManager) {
        uni.showToast({
          title: '当前环境不支持录音',
          icon: 'none'
        });
        return;
      }

      // 检查录音权限
      uni.getSetting({
        success: (res) => {
          if (res.authSetting['scope.record'] === true) {
            // 已有权限，直接开始录音
            this.doStartRecord();
          } else if (res.authSetting['scope.record'] === false) {
            // 权限被拒绝，引导用户去设置
            uni.showModal({
              title: '权限申请',
              content: '需要录音权限才能使用语音功能，请在设置中开启',
              showCancel: true,
              confirmText: '去设置',
              success: (modalRes) => {
                if (modalRes.confirm) {
                  uni.openSetting({
                    success: (settingRes) => {
                      console.log('权限设置结果:', settingRes.authSetting);
                      if (settingRes.authSetting['scope.record']) {
                        // 权限开启后重新初始化录音管理器
                        this.initRecorderManager();
                        uni.showToast({
                          title: '权限已开启，请重试录音',
                          icon: 'none'
                        });
                      }
                    }
                  });
                }
              }
            });
          } else {
            // 未设置过权限，请求权限
            uni.authorize({
              scope: 'scope.record',
              success: () => {
                // 授权成功，重新初始化录音管理器并开始录音
                this.initRecorderManager();
                setTimeout(() => {
                  this.doStartRecord();
                }, 100); // 稍等片刻确保初始化完成
              },
              fail: (err) => {
                console.log('录音权限获取失败:', err);
                uni.showModal({
                  title: '权限申请',
                  content: '需要录音权限才能使用语音功能，请在设置中开启',
                  showCancel: true,
                  confirmText: '去设置',
                  success: (res) => {
                    if (res.confirm) {
                      uni.openSetting({
                        success: (settingRes) => {
                          console.log('权限设置结果:', settingRes.authSetting);
                          if (settingRes.authSetting['scope.record']) {
                            // 权限开启后重新初始化录音管理器
                            this.initRecorderManager();
                            uni.showToast({
                              title: '权限已开启，请重试录音',
                              icon: 'success'
                            });
                          }
                        }
                      });
                    }
                  }
                });
              }
            });
          }
        },
        fail: (err) => {
          console.error('获取设置失败:', err);
          uni.showToast({
            title: '获取权限状态失败',
            icon: 'none'
          });
        }
      });
    },

    // 执行录音操作
    doStartRecord() {
      this.isRecording = true;
      this.isCancel = false;

      try {
        // 开始录音
        this.recorderManager.start({
          format: 'mp3',
          sampleRate: 16000,
          numberOfChannels: 1,
          encodeBitRate: 96000
        });

        // 计时
        this.recordDuration = 0;
        this.recordTimer = setInterval(() => {
          this.recordDuration++;
          // 最长录音30秒
          if (this.recordDuration >= 30) {
            uni.showToast({
              title: '录音时长已达上限',
              icon: 'none',
              duration: 1000
            });
            this.stopRecord();
          }
        }, 1000);

      } catch (err) {
        console.error('启动录音失败:', err);
        uni.showToast({
          title: '启动录音失败',
          icon: 'none'
        });
        this.resetRecordState();
      }
    },

    // 停止录音
    stopRecord() {
      if (this.isRecording) {
        try {
          this.recorderManager.stop();
        } catch (e) {
          console.error('停止录音失败:', e);
          // 强制重置状态
          this.resetRecordState();
        }
      }
    },

    // 取消录音
    cancelRecord() {
      if (this.isRecording) {
        this.isCancel = true;
        try {
          this.recorderManager.stop();
        } catch (e) {
          console.error('取消录音失败:', e);
          // 强制重置状态
          this.resetRecordState();
        }
      }
    },

    // 处理滑动事件
    handleTouchMove(e) {
      if (!this.isRecording) return;

      // 获取触摸位置
      const touchY = e.touches[0].clientY;
      // 获取页面滚动位置
      const query = uni.createSelectorQuery();
      query.select('.record-btn').boundingClientRect((res) => {
        if (res) {
          // 向上滑动超过50px判定为取消
          if (res.top - touchY > 50) {
            this.isCancel = true;
          } else {
            this.isCancel = false;
          }
        }
      });
      query.exec();
    },

    // 播放/停止播放语音
    togglePlay(voiceIndex) {
      const voice = this.voiceList[voiceIndex];

      if (this.isPlaying && this.playingIndex === voiceIndex) {
        // 停止播放
        this.innerAudioContext.stop();
        this.isPlaying = false;
        this.playingIndex = -1;
      } else {
        // 播放选中的语音
        this.innerAudioContext.stop();
        this.innerAudioContext.src = voice.tempFilePath;
        this.innerAudioContext.play();

        this.isPlaying = true;
        this.playingIndex = voiceIndex;
      }
    },

    // 格式化时间显示
    formatTime(seconds) {
      if (seconds < 60) {
        return `${seconds}''`;
      } else {
        const min = Math.floor(seconds / 60);
        const sec = seconds % 60;
        return `${min}'${sec}''`;
      }
    },

    // 解析Markdown格式
    parseMarkdown(text) {
      if (!text || typeof text !== 'string') {
        return text;
      }

      let html = text;

      // 转义HTML字符
      html = html.replace(/&/g, '&amp;')
                 .replace(/</g, '&lt;')
                 .replace(/>/g, '&gt;');

      // 解析标题 (##、###)
      html = html.replace(/^### (.*$)/gim, '<h3 class="md-h3">$1</h3>');
      html = html.replace(/^## (.*$)/gim, '<h2 class="md-h2">$1</h2>');
      html = html.replace(/^# (.*$)/gim, '<h1 class="md-h1">$1</h1>');

      // 解析粗体 **text**
      html = html.replace(/\*\*(.*?)\*\*/g, '<strong class="md-bold">$1</strong>');

      // 解析斜体 *text*
      html = html.replace(/\*(.*?)\*/g, '<em class="md-italic">$1</em>');

      // 解析行内代码 `code`
      html = html.replace(/`([^`]+)`/g, '<code class="md-code">$1</code>');

      // 解析代码块 ```code```
      html = html.replace(/```([\s\S]*?)```/g, '<pre class="md-pre"><code class="md-code-block">$1</code></pre>');

      // 解析无序列表
      html = html.replace(/^\* (.+)$/gim, '<li class="md-li">$1</li>');
      html = html.replace(/(<li class="md-li">.*<\/li>)/s, '<ul class="md-ul">$1</ul>');

      // 解析有序列表
      html = html.replace(/^\d+\. (.+)$/gim, '<li class="md-li-ordered">$1</li>');
      html = html.replace(/(<li class="md-li-ordered">.*<\/li>)/s, '<ol class="md-ol">$1</ol>');

      // 解析链接 [text](url)
      html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a class="md-link" href="$2">$1</a>');

      // 解析换行
      html = html.replace(/\n/g, '<br/>');

      // 解析引用 > text
      html = html.replace(/^&gt; (.+)$/gim, '<blockquote class="md-quote">$1</blockquote>');

      return html;
    }
  }
};
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background-color: #f5f5f5;
  padding-bottom: 150rpx;
}

/* 消息列表样式 */
.message-list {
  flex: 1;
  padding: 20rpx;
  height: calc(100vh - 150rpx);
}

.message-wrapper {
  margin-bottom: 30rpx;
}

.message-item {
  display: flex;
  max-width: 80%;
}

/* 用户消息样式（右侧绿色） */
.user-message {
  justify-content: flex-end;
  margin-left: auto;
}

.user-content {
  background-color: #07c160;
  color: #fff;
  padding: 25rpx 35rpx;
  border-radius: 30rpx 30rpx 10rpx 30rpx;
  position: relative;
}

.user-content::after {
  content: '';
  position: absolute;
  right: -10rpx;
  bottom: 0;
  width: 0;
  height: 0;
  border: 10rpx solid transparent;
  border-left-color: #07c160;
  border-bottom: none;
}

/* 系统消息样式（左侧灰色） */
.system-message {
  justify-content: flex-start;
}

.system-content {
  background-color: #ffffff;
  color: #333;
  padding: 25rpx 35rpx;
  border-radius: 10rpx 30rpx 30rpx 30rpx;
  position: relative;
  border: 1rpx solid #e5e5e5;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}

.system-content::after {
  content: '';
  position: absolute;
  left: -10rpx;
  bottom: 0;
  width: 0;
  height: 0;
  border: 10rpx solid transparent;
  border-right-color: #ffffff;
  border-bottom: none;
}

/* 消息内容样式 */
.text-message {
  font-size: 36rpx;
  line-height: 1.5;
  word-wrap: break-word;
}

.voice-message {
  display: flex;
  align-items: center;
  gap: 15rpx;
  min-width: 120rpx;
}

.voice-icon {
  width: 30rpx;
  height: 30rpx;
  fill: currentColor;
}

.voice-duration {
  font-size: 30rpx;
}

/* 输入区域样式 */
.input-area {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: #fff;
  border-top: 1rpx solid #e5e5e5;
  padding: 20rpx;
  display: flex;
  flex-direction: column;
}

/* 录音提示样式 */
.record-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.record-modal {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60rpx;
  background-color: rgba(0, 0, 0, 0.8);
  border-radius: 40rpx;
  backdrop-filter: blur(10rpx);
}

.record-circle {
  width: 120rpx;
  height: 120rpx;
  background-color: #ff4d4f;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 30rpx;
  animation: recordPulse 1.5s ease-in-out infinite;
  box-shadow: 0 0 30rpx rgba(255, 77, 79, 0.5);
}

.record-circle.cancel {
  background-color: #ff9800;
  box-shadow: 0 0 30rpx rgba(255, 152, 0, 0.5);
  animation: cancelShake 0.3s ease-in-out infinite;
}

.record-icon {
  width: 60rpx;
  height: 60rpx;
  fill: #fff;
}

.record-time {
  font-size: 48rpx;
  font-weight: bold;
  color: #fff;
  margin-bottom: 20rpx;
}

.record-tip {
  font-size: 28rpx;
  text-align: center;
}

.normal-text {
  color: #ccc;
}

.cancel-text {
  color: #ff9800;
  font-weight: bold;
}

@keyframes recordPulse {
  0% {
    transform: scale(1);
    box-shadow: 0 0 30rpx rgba(255, 77, 79, 0.5);
  }
  50% {
    transform: scale(1.1);
    box-shadow: 0 0 50rpx rgba(255, 77, 79, 0.8);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 30rpx rgba(255, 77, 79, 0.5);
  }
}

@keyframes cancelShake {
  0%, 100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-5rpx);
  }
  75% {
    transform: translateX(5rpx);
  }
}

/* 输入区域样式 */
.input-mode {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.voice-btn {
  width: 90rpx;
  height: 90rpx;
  border-radius: 50%;
  background-color: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
}

.voice-btn image {
  width: 50rpx;
  height: 50rpx;
}

.icon {
  width: 50rpx;
  height: 50rpx;
  fill: #666;
}

.message-input {
  flex: 1;
  height: 90rpx;
  border: 1rpx solid #e5e5e5;
  border-radius: 45rpx;
  padding: 0 35rpx;
  font-size: 32rpx;
  background-color: #f5f5f5;
}

.send-btn {
  width: 120rpx;
  height: 90rpx;
  border-radius: 45rpx;
  background-color: #e5e5e5;
  color: #999;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30rpx;
  transition: all 0.3s;
}

.send-btn.active {
  background-color: #07c160;
  color: #fff;
}

/* 语音模式样式 */
.voice-mode {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.keyboard-btn {
  width: 90rpx;
  height: 90rpx;
  border-radius: 50%;
  background-color: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
}

.keyboard-btn image {
  width: 50rpx;
  height: 50rpx;
}

.keyboard-icon {
  width: 50rpx;
  height: 50rpx;
}

.record-btn {
  flex: 1;
  height: 90rpx;
  border-radius: 45rpx;
  background-color: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
  transition: all 0.3s;
}

.record-btn.recording {
  background-color: #ff4d4f;
}

.record-btn.cancel {
  background-color: #ff9800;
}

.btn-text {
  font-size: 32rpx;
  color: #333;
}

.record-btn.recording .btn-text,
.record-btn.cancel .btn-text {
  color: #fff;
}

.record-hint {
  font-size: 24rpx;
  color: #999;
  text-align: center;
  margin-top: 15rpx;
}

/* Markdown样式 */
.text-message .md-h1 {
  font-size: 44rpx;
  font-weight: bold;
  color: #333;
  margin: 20rpx 0 15rpx 0;
  line-height: 1.4;
}

.text-message .md-h2 {
  font-size: 40rpx;
  font-weight: bold;
  color: #333;
  margin: 18rpx 0 12rpx 0;
  line-height: 1.4;
}

.text-message .md-h3 {
  font-size: 38rpx;
  font-weight: bold;
  color: #333;
  margin: 15rpx 0 10rpx 0;
  line-height: 1.4;
}

.text-message .md-bold {
  font-weight: bold;
  color: #333;
}

.text-message .md-italic {
  font-style: italic;
  color: #666;
}

.text-message .md-code {
  background-color: #f1f3f4;
  color: #d73502;
  padding: 4rpx 8rpx;
  border-radius: 6rpx;
  font-family: Consolas, Monaco, 'Courier New', monospace;
  font-size: 32rpx;
}

.text-message .md-pre {
  background-color: #f6f8fa;
  border: 1rpx solid #e1e4e8;
  border-radius: 12rpx;
  padding: 20rpx;
  margin: 15rpx 0;
  overflow-x: auto;
}

.text-message .md-code-block {
  font-family: Consolas, Monaco, 'Courier New', monospace;
  font-size: 30rpx;
  color: #24292e;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-all;
}

.text-message .md-ul,
.text-message .md-ol {
  margin: 15rpx 0;
  padding-left: 40rpx;
}

.text-message .md-li,
.text-message .md-li-ordered {
  margin: 8rpx 0;
  line-height: 1.6;
  list-style-position: outside;
}

.text-message .md-li {
  list-style-type: disc;
}

.text-message .md-li-ordered {
  list-style-type: decimal;
}

.text-message .md-link {
  color: #0366d6;
  text-decoration: underline;
}

.text-message .md-quote {
  border-left: 8rpx solid #dfe2e5;
  padding: 0 32rpx;
  margin: 15rpx 0;
  color: #6a737d;
  background-color: #f6f8fa;
  border-radius: 0 8rpx 8rpx 0;
}
</style>